package com.demo.wrapper.interfaces;

import com.demo.wrapper.constance.DefaultValueConstance;
import com.demo.wrapper.enums.QueryEnum;
import com.demo.wrapper.pojo.Arg;
import com.demo.wrapper.enums.OperatorEnum;

import java.util.Collection;
import java.util.Optional;


/**
 * 查询接口
 *
 * @param <Wrapper> 条件拼接类，需继承Query接口
 * @author 19242
 */
public interface IEsQueryWrapper<Wrapper extends IEsQueryWrapper<Wrapper>> extends IBaseWrapper<Wrapper> {

    /**
     * 等于
     *
     * @param column 字段名
     * @param val    值
     * @return this
     */
    default Wrapper eq(String column, Object val) {
        return eq(column, val, DefaultValueConstance.BOOST);
    }

    /**
     * 等于
     *
     * @param column 字段名
     * @param val    值
     * @param boost  权重
     * @return this
     */
    default Wrapper eq(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.TERM, column, val, boost));
    }

    /**
     * in
     *
     * @param column 字段名
     * @param val    值
     * @return this
     */
    default Wrapper in(String column, Collection<?> val) {
        return in(column, val, DefaultValueConstance.BOOST);
    }

    /**
     * in
     *
     * @param column 字段名
     * @param val    值
     * @param boost  权重
     * @return this
     */
    default Wrapper in(String column, Collection<?> val, float boost) {
        return addQuery(new Arg(QueryEnum.TERMS, column, val, boost));
    }

    /**
     * 分词查询
     *
     * @param column 字段名
     * @param val    值
     * @return this
     */
    default Wrapper match(String column, Object val) {
        return match(column, val, DefaultValueConstance.BOOST, OperatorEnum.OR);
    }

    /**
     * 分词查询
     *
     * @param column 字段名
     * @param val    值
     * @param boost  权重
     * @return this
     */
    default Wrapper match(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.MATCH, column, val, boost, OperatorEnum.OR));
    }

    /**
     * 分词查询
     *
     * @param column   字段名
     * @param val      值
     * @param operator 关系
     * @return this
     */
    default Wrapper match(String column, Object val, OperatorEnum operator) {
        return addQuery(new Arg(QueryEnum.MATCH, column, val, DefaultValueConstance.BOOST, operator));
    }

    /**
     * 分词查询
     *
     * @param column   字段名
     * @param val      值
     * @param boost    权重
     * @param operator 关系
     * @return this
     */
    default Wrapper match(String column, Object val, float boost, OperatorEnum operator) {
        return addQuery(new Arg(QueryEnum.MATCH, column, val, boost, operator));
    }

    /**
     * 查全部
     *
     * @return this
     */
    default Wrapper matchAll() {
        return matchAll(DefaultValueConstance.BOOST);
    }

    /**
     * 查全部
     *
     * @param boost
     * @return this
     */
    default Wrapper matchAll(float boost) {
        return addQuery(new Arg(QueryEnum.MATCH_ALL, null, null, boost));
    }

    /**
     * 分词匹配
     *
     * @param column
     * @param val
     * @return
     */
    default Wrapper matchPhrase(String column, Object val) {
        return matchPhrase(column, val, DefaultValueConstance.BOOST);
    }

    /**
     * 分词匹配
     *
     * @param column
     * @param val
     * @param boost
     * @return this
     */
    default Wrapper matchPhrase(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.MATCH_PHRASE, column, val, boost));
    }

    /**
     * 前缀匹配
     *
     * @param column
     * @param val
     * @return this
     */
    default Wrapper matchPhrasePrefix(String column, Object val) {
        return addQuery(new Arg(QueryEnum.MATCH_PHRASE_PREFIX, column, val, DefaultValueConstance.BOOST, DefaultValueConstance.MAX_EXPANSIONS));
    }

    /**
     * 前缀匹配
     *
     * @param column
     * @param val
     * @param boost
     * @return
     */
    default Wrapper matchPhrasePrefix(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.MATCH_PHRASE_PREFIX, column, val, boost, DefaultValueConstance.MAX_EXPANSIONS));
    }

    /**
     * 前缀匹配
     *
     * @param column
     * @param val
     * @param maxExpansions
     * @return
     */
    default Wrapper matchPhrasePrefix(String column, Object val, int maxExpansions) {
        return addQuery(new Arg(QueryEnum.MATCH_PHRASE_PREFIX, column, val, DefaultValueConstance.BOOST, maxExpansions));
    }

    /**
     * 前缀匹配
     *
     * @param column
     * @param val
     * @param boost
     * @param maxExpansions
     * @return
     */
    default Wrapper matchPhrasePrefix(String column, Object val, float boost, int maxExpansions) {
        return addQuery(new Arg(QueryEnum.MATCH_PHRASE_PREFIX, column, val, boost, maxExpansions));
    }


    /**
     * 多字段匹配
     *
     * @param val     值
     * @param columns 字段
     * @return
     */
    default Wrapper multiMatch(Object val, String... columns) {
        return multiMatch(val, DefaultValueConstance.BOOST, OperatorEnum.OR, DefaultValueConstance.MIN_SHOULD_MATCH, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val     值
     * @param boost   权重
     * @param columns 字段
     * @return
     */
    default Wrapper multiMatch(Object val, float boost, String... columns) {
        return multiMatch(val, boost, OperatorEnum.OR, DefaultValueConstance.MIN_SHOULD_MATCH, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val                值
     * @param minimumShouldMatch 最小匹配度
     * @param columns            字段
     * @return
     */
    default Wrapper multiMatch(Object val, int minimumShouldMatch, String... columns) {
        return multiMatch(val, DefaultValueConstance.BOOST, OperatorEnum.OR, minimumShouldMatch, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val      值
     * @param operator 逻辑
     * @param columns  字段
     * @return
     */
    default Wrapper multiMatch(Object val, OperatorEnum operator, String... columns) {
        return multiMatch(val, DefaultValueConstance.BOOST, operator, DefaultValueConstance.MIN_SHOULD_MATCH, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val                值
     * @param boost              权重
     * @param minimumShouldMatch 最小匹配度
     * @param columns            字段
     * @return
     */
    default Wrapper multiMatch(Object val, float boost, int minimumShouldMatch, String... columns) {
        return multiMatch(val, boost, OperatorEnum.OR, minimumShouldMatch, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val      值
     * @param operator 逻辑
     * @param boost    权重
     * @param columns  字段
     * @return
     */
    default Wrapper multiMatch(Object val, float boost, OperatorEnum operator, String... columns) {
        return multiMatch(val, boost, operator, DefaultValueConstance.MIN_SHOULD_MATCH, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val                值
     * @param operator           逻辑
     * @param minimumShouldMatch 最小匹配度
     * @param columns            字段
     * @return
     */
    default Wrapper multiMatch(Object val, OperatorEnum operator, int minimumShouldMatch, String... columns) {
        return multiMatch(val, DefaultValueConstance.BOOST, operator, minimumShouldMatch, columns);
    }

    /**
     * 多字段匹配
     *
     * @param val                值
     * @param operator           逻辑
     * @param boost              权重
     * @param minimumShouldMatch 最小匹配度
     * @param columns            字段
     * @return this
     */
    default Wrapper multiMatch(Object val, float boost, OperatorEnum operator, int minimumShouldMatch, String... columns) {
        return addQuery(new Arg(QueryEnum.MULTI_MATCH, null, val, boost, operator, minimumShouldMatch, columns));
    }

    default Wrapper gt(String column, Object val) {
        return gt(column, val, DefaultValueConstance.BOOST);
    }

    default Wrapper gt(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.GT, column, val, boost));
    }

    default Wrapper ge(String column, Object val) {
        return ge(column, val, DefaultValueConstance.BOOST);
    }

    default Wrapper ge(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.GE, column, val, boost));
    }

    default Wrapper lt(String column, Object val) {
        return lt(column, val, DefaultValueConstance.BOOST);
    }

    default Wrapper lt(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.LT, column, val, boost));
    }

    default Wrapper le(String column, Object val) {
        return le(column, val, DefaultValueConstance.BOOST);
    }

    default Wrapper le(String column, Object val, float boost) {
        return addQuery(new Arg(QueryEnum.LE, column, val, boost));
    }

    default Wrapper between(String column, Object ge, Object le) {
        return between(column, ge, le, DefaultValueConstance.BOOST);
    }

    default Wrapper between(String column, Object ge, Object le, float boost) {
        return addQuery(new Arg(QueryEnum.BETWEEN, column, null, boost, ge, le));
    }

    /**
     * like
     *
     * @param column 字段
     * @param val    值，会字段拼接 *val*
     * @return
     */
    default Wrapper like(String column, Object val) {
        return like(column, val, DefaultValueConstance.BOOST);
    }

    /**
     * like
     *
     * @param column 字段
     * @param val    值，会字段拼接 *val*
     * @param boost  权重
     * @return
     */
    default Wrapper like(String column, Object val, float boost) {
        String newVal = Optional.ofNullable(val)
                .map(v -> DefaultValueConstance.ALL + v + DefaultValueConstance.ALL)
                .orElse(DefaultValueConstance.ALL);
        return addQuery(new Arg(QueryEnum.WILDCARD, column, newVal, boost));
    }

    /**
     * like
     *
     * @param column 字段
     * @param val    手动拼接通配符
     * @return
     */
    default Wrapper like(String column, Object... val) {
        return like(column, DefaultValueConstance.BOOST, val);
    }

    /**
     * like
     *
     * @param column 字段
     * @param boost  权重
     * @param val    手动拼接通配符
     * @return
     */
    default Wrapper like(String column, float boost, Object... val) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Object o : val) {
            stringBuilder.append(o);
        }
        return addQuery(new Arg(QueryEnum.WILDCARD, column, stringBuilder.toString(), boost));
    }

    /**
     * 字段存在
     *
     * @param column 字段
     * @return
     */
    default Wrapper exists(String column) {
        return addQuery(new Arg(QueryEnum.EXISTS, column, null, DefaultValueConstance.BOOST));
    }

    /**
     * 字段存在
     *
     * @param column 字段
     * @param boost  权重
     * @return
     */
    default Wrapper exists(String column, float boost) {
        return addQuery(new Arg(QueryEnum.EXISTS, column, null, boost));
    }

    /**
     * 添加条件
     *
     * @param arg 条件实体类
     * @return this
     */
    Wrapper addQuery(Arg arg);

    /**
     * 清空条件
     *
     * @return this
     */
    Wrapper clearQuery();
}
